package ru.sstu.renju.core;

/**
 * <code>Row</code> class represents row of 5 cells.
 *
 * @author denis_murashev
 * @since Renju 1.0
 */
public final class Row {

	private final int x;
	private final int y;
	private final Direction direction;

	/**
	 * Initializes row.
	 *
	 * @param game      game
	 * @param x         x of start cell
	 * @param y         y of start cell
	 * @param direction direction
	 */
	public Row(Game game, int x, int y, Direction direction) {
		if (direction == null || !direction.validate(game, x, y)) {
			throw new IllegalArgumentException();
		}
		this.x = x;
		this.y = y;
		this.direction = direction;
	}

	/**
	 * @return the x
	 */
	public int getX() {
		return x;
	}

	/**
	 * @return the y
	 */
	public int getY() {
		return y;
	}

	/**
	 * @return the direction
	 */
	public Direction getDirection() {
		return direction;
	}

	@Override
	public String toString() {
		return direction + " from (" + x + ", " + y + ")";
	}

	/**
	 * <code>Direction</code> enumeration represents row directions.
	 *
	 * @author denis_murashev
	 * @since Renju 1.0
	 */
	public enum Direction {

		/**
		 * Down.
		 */
		DOWN(0, 1),

		/**
		 * Down and right.
		 */
		DOWN_RIGHT(1, 1),

		/**
		 * Right.
		 */
		RIGHT(1, 0),

		/**
		 * Up and right.
		 */
		UP_RIGHT(1, -1);

		private final int dx;
		private final int dy;

		private Direction(int dx, int dy) {
			this.dx = dx;
			this.dy = dy;
		}

		/**
		 * @return the dx
		 */
		public int getDx() {
			return dx;
		}

		/**
		 * @return the dy
		 */
		public int getDy() {
			return dy;
		}

		private boolean validate(Game game, int x, int y) {
			int gameSize = game.getSize();
			int rowSize = game.getConfig().getRowSize();
			return checkValue(x, game.getSize())
					&& checkValue(x + dx * (rowSize - 1), gameSize)
					&& checkValue(y, game.getSize())
					&& checkValue(y + dy * (rowSize - 1), gameSize);
		}

		private boolean checkValue(int value, int size) {
			return value >= 0 && value < size;
		}
	}
}
